package main

import (
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"io"
	"net/http"
	"os"
	"time"
)

// ProgressWriter 结构体用于跟踪下载进度
type ProgressWriter struct {
	Writer       io.Writer
	Total        int64
	Downloaded   int64
	LastReported int
}

func (pw *ProgressWriter) Write(p []byte) (int, error) {
	n, err := pw.Writer.Write(p)
	if err != nil {
		return n, err
	}

	pw.Downloaded += int64(n)
	percentage := int(float64(pw.Downloaded) / float64(pw.Total) * 100)

	// 避免频繁打印，只在进度变化时打印
	if percentage != pw.LastReported && percentage%1 == 0 {
		fmt.Printf("\r下载进度: %d%%", percentage)
		pw.LastReported = percentage
	}

	return n, nil
}

func main() {
	url := os.Args[1]

	// 发起 HTTP GET 请求
	resp, err := http.Get(url)
	if err != nil {
		fmt.Printf("无法下载内容: %v\n", err)
		return
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		fmt.Printf("请求失败，状态码: %d\n", resp.StatusCode)
		return
	}

	// 获取内容长度
	contentLength := resp.ContentLength
	if contentLength <= 0 {
		fmt.Println("无法获取内容长度，进度无法显示。")
		return
	}

	// 创建一个 MD5 哈希对象
	hash := md5.New()

	// 创建 ProgressWriter
	pw := &ProgressWriter{
		Writer: hash,
		Total:  contentLength,
	}

	// 启动一个计时器用于刷新进度条
	ticker := time.NewTicker(500 * time.Millisecond)
	defer ticker.Stop()

	done := make(chan bool)

	go func() {
		for {
			select {
			case <-ticker.C:
				// 可以在这里添加更多的进度信息或刷新界面
			case <-done:
				return
			}
		}
	}()

	// 将响应体内容复制到 ProgressWriter 中，同时计算 MD5
	_, err = io.Copy(pw, resp.Body)
	if err != nil {
		fmt.Printf("\n读取内容失败: %v\n", err)
		return
	}

	done <- true

	// 打印一个新行，确保后续输出不在同一行
	fmt.Println()

	// 计算 MD5 值
	md5Bytes := hash.Sum(nil)
	md5String := hex.EncodeToString(md5Bytes)

	fmt.Printf("URL: %s\n内容的 MD5: %s\n", url, md5String)
}
